<template>
	<div ref="container" @click="roamFn">
		<div style="position: absolute; z-index: 10" class="flex-center w100 h100" v-show="loading">
			<dv-decoration :scale="2">
				<span class="fw" style="font-size: 30px"> {{ percentComplete }}% </span>
			</dv-decoration>
		</div>
		<my-compass :keyType="keyType" />
		<div class="left-control">
			<div class="view-port-follow">
				<el-checkbox v-model="viewPortFollow" label="视角跟随" size="large" style="margin-right: 10px" />
				<el-dropdown trigger="click" @command="commandFn">
					<div class="view-port-type">
						{{ viewPortFollowType }}<el-icon class="el-icon--right"><arrow-down /></el-icon>
					</div>
					<template #dropdown>
						<el-dropdown-menu>
							<el-dropdown-item v-for="(item, i) in viewPortList" :key="item.name" :command="i">{{ item.name }}</el-dropdown-item>
						</el-dropdown-menu>
					</template>
				</el-dropdown>
			</div>
		</div>
		<Teleport to="body">
			<div class="flex m-around p-10 label" ref="label1">
				<div class="flex">
					<iconpark-icon name="caigao" fill="#fff"></iconpark-icon>
					<div class="flex-col m-l-5">
						<span class="val">{{ data?.leftData?.height }}</span>
						<span class="name">左采高</span>
					</div>
				</div>
				<div class="flex">
					<iconpark-icon name="guntongdianliubiankuang" fill="#fff"></iconpark-icon>
					<div class="flex-col m-l-5">
						<span class="val">{{ data?.leftData?.electricity }}&nbsp;A</span>
						<span class="name">滚筒电流</span>
					</div>
				</div>
				<div class="flex">
					<iconpark-icon name="guntongwendu" fill="#fff"></iconpark-icon>
					<div class="flex-col m-l-5">
						<span class="val">{{ data?.leftData?.temperature }}°</span>
						<span class="name">滚筒温度</span>
					</div>
				</div>
			</div>
			<div class="flex p-10 label" style="width: 150px" ref="label2">
				<iconpark-icon name="wasinongdujitoujiweiwasi" fill="#fff"></iconpark-icon>
				<div class="flex-col m-l-5">
					<span class="val">{{ data?.pullingSpeed }} m/min</span>
					<span class="name">牵引速度</span>
				</div>
			</div>
			<div class="flex m-around p-10 label" ref="label3">
				<div class="flex">
					<iconpark-icon name="caigao" fill="#fff"></iconpark-icon>
					<div class="flex-col m-l-5">
						<span class="val">{{ data?.rightData?.height }}m</span>
						<span class="name">右采高</span>
					</div>
				</div>
				<div class="flex">
					<iconpark-icon name="guntongdianliubiankuang" fill="#fff"></iconpark-icon>
					<div class="flex-col m-l-5">
						<span class="val">{{ data?.rightData?.electricity }}&nbsp;A</span>
						<span class="name">滚筒电流</span>
					</div>
				</div>
				<div class="flex">
					<iconpark-icon name="guntongwendu" fill="#fff"></iconpark-icon>
					<div class="flex-col m-l-5">
						<span class="val">{{ data?.rightData?.temperature }}°</span>
						<span class="name">滚筒温度</span>
					</div>
				</div>
			</div>
		</Teleport>
	</div>
</template>

<script setup name="FullyMechanizedFace_threePage">
import { DBUtil } from '@u/indexedDB'
import {
	useResizeObserver,
	THREE,
	GLTFloaderFn,
	clock,
	cameraFn,
	collideCheck,
	compassRotate,
	cameraTwwen,
	TWEEN,
	rendererFn,
	labelRendererFn,
	mixersFn,
	CSS3DSprite,
	keyType
} from '@u/threeMinx'

let container = shallowRef(null), // 模型渲染的Demo节点
	renderer, //  WebGLRenderer渲染器
	scene, // 场景
	camera, // 相机
	cameraRender,
	labelRenderer,
	loading = ref(false),
	percentComplete = ref(0)

// 组件宽高
let width, height
useResizeObserver(container, (entries) => {
	width = entries[0].contentRect.width
	height = entries[0].contentRect.height
	camera.aspect = width / height
	camera.updateProjectionMatrix()
	renderer.setSize(width, height)
	labelRenderer.setSize(width, height)
})
// 初始化生命周期
onMounted(() => {
	loading.value = true
	init()
})
onBeforeUnmount(() => {
	cancelAnimationFrame(requestAnimationFrameIndex)
	// 释放显存
	renderer?.dispose()
	// 释放内存
	container = null
	scene = null
	labelRenderer = null
})

/**
 * 视角跟随，视角切换
 */
const viewPortList = [
	{ name: '默认视角', position: { x: -74, y: -5, z: -2 }, lookAt: { x: -50, y: -5, z: -16 } },
	{ name: '采煤机视角', position: { x: 69, y: -5, z: -2 }, lookAt: { x: 0.5, y: -14.6, z: -6.1 } }
]
let viewPortFollow = ref(false)
let viewPortFollowType = ref(viewPortList[0].name)
function commandFn(e) {
	viewPortFollowType.value = viewPortList[e].name
	cameraTwwen({ camera, newP: viewPortList[e].position, newT: viewPortList[e].lookAt })
}

function init() {
	// 场景
	scene = new THREE.Scene()
	// 相机
	camera = new THREE.PerspectiveCamera(45, width / height, 1, 2000)
	{
		const { x, y, z } = viewPortList[0].position
		camera.position.set(x, y, z)
	}
	{
		const { x, y, z } = viewPortList[0].lookAt
		camera.lookAt(x, y, z)
	}
	cameraRender = cameraFn(camera)
	scene.add(camera)
	// 渲染器
	renderer = rendererFn(container)
	// label渲染器
	labelRenderer = labelRendererFn(container)
	// 灯光
	lights()
	// 加载器
	loaderFn()
}
let objects = [],
	mixers = [],
	model,
	modelWa
function loaderFn() {
	new DBUtil().get(`${import.meta.env.VITE_APP_BASE_BASE || '/'}model/智能综采.glb`).then((blob) => {
		let url = URL.createObjectURL(blob)
		GLTFloaderFn.load(
			url,
			(object) => {
				loading.value = false
				model = object.scene
				scene.add(model)
				objects = [model.getObjectByName('矿道')]
				model.getObjectByName('主体').position.x = -55
				modelWa = model.getObjectByName('主体')
				// 液压支架，刮板运输机
				for (let i = 0; i < 27; i++) {
					const mc = model.getObjectByName('液压支架').clone()
					mc.translateX(i * 5.6)
					scene.add(mc)
					const mc2 = model.getObjectByName('刮板运输机').clone()
					mc2.translateX(i * 6)
					scene.add(mc2)
					const mc3 = model.getObjectByName('煤堆').clone()
					mc3.translateX(i * 6)
					scene.add(mc3)
				}
				labelFn()
				mixers.push(mixersFn(object))
				// 渲染器
				render()
			},
			(xhr) => {
				if (xhr.lengthComputable) percentComplete.value = Math.round((xhr.loaded / xhr.total) * 100, 2)
			}
		)
	})
}

/**
 * 灯光
 */
function lights() {
	// 自然光
	scene.add(new THREE.AmbientLight(0xffffff, 0.5))
	// 平行光（模拟太阳光）
	let light = new THREE.DirectionalLight(0xffffff, 1)
	light.position.set(-5.856, 5.322, -0.915)
	scene.add(light)
}

// 采煤机信息-添加label
const props = defineProps({
		data: {
			type: Object,
			required: true
		}
	}),
	position = [
		[-11, 0, 0],
		[-2, -0.8, 2],
		[7, 0, 0]
	],
	labelGroup = new THREE.Group(),
	label1 = ref(null),
	label2 = ref(null),
	label3 = ref(null)

labelGroup.position.set(2, 1.5, -1)
function labelFn() {
	modelWa.add(labelGroup)
	position.forEach((item, i) => {
		let dom = i == 0 ? label1 : i == 1 ? label2 : label3
		const pointLabel = new CSS3DSprite(dom.value)
		pointLabel.position.set(...item)
		pointLabel.scale.set(0.01, 0.01, 0.01)
		labelGroup.add(pointLabel)
	})
}

// 创建漫游线路
let curve
function pathFn() {
	// 创建组合曲线对象CurvePath
	curve = new THREE.CurvePath()
	// 把多个线条插入到CurvePath中
	curve.curves.push(new THREE.LineCurve3(new THREE.Vector3(-55, -6.2, -4.7), new THREE.Vector3(60, -6.2, -4.7)))
}
pathFn()

// 渲染逻辑
let requestAnimationFrameIndex,
	loop = 0,
	progress = 0,
	speed = 0.0001

function render() {
	// 漫游
	keyType.value = cameraRender(objects)
	compassRotate(camera)

	if (props.data.state == 1) {
		model.getObjectByName('立方体005_4').material.map.offset.y += 0.05
		// 运行动画
		mixers.forEach((mixer) => mixer.update(clock.getDelta()))
		// 巡检移动动画
		if (curve) {
			if (loop % 2 == 0) {
				progress += speed
			} else {
				progress -= speed
			}
			if (progress > 1 - speed || progress < speed) loop++

			//取路径上当前点的坐标
			const { x, y, z } = curve.getPointAt(progress)
			const { x: modelWaX, y: modelWaY, z: modelWaZ } = modelWa.position
			//设置车模型坐标为在相机路径上当前点的位置
			modelWa?.position?.set(x, y, z)
			// 视角跟随
			if (viewPortFollow.value) {
				const { x: cameraX, y: cameraY, z: cameraZ } = camera.position.clone()
				const cameraNew = new THREE.Vector3(cameraX, cameraY, cameraZ).add(
					new THREE.Vector3(x, y, z).sub(new THREE.Vector3(modelWaX, modelWaY, modelWaZ))
				)
				if (!collideCheck(objects, cameraNew)) {
					const { x, y, z } = cameraNew
					camera.position.set(x, y, z)
				}
				{
					const { x, y, z } = curve.getPointAt(progress)
					// 转向
					camera.lookAt(x, y, z)
				}
			}
		}
	}

	labelRenderer?.render(scene, camera)
	TWEEN?.update()
	renderer?.render(scene, camera)
	requestAnimationFrameIndex = requestAnimationFrame(render)
}
</script>

<style lang="scss" scoped>
.left-control {
	position: absolute;
	left: 450px;
	top: 20px;
	z-index: 3;
	display: flex;
	flex-direction: flex-end;
	.view-port-type {
		color: #fff;
		border-radius: 4px;
		font-size: 16px;
		opacity: 1;
		background: linear-gradient(180deg, #2c62b3 1%, #0e3064 100%);
		box-shadow: 0px 2px 2px 0px #091121, inset 0px -1px 2px 0px rgba(255, 255, 255, 0.4);
		border: none;
		height: 40px !important;
		padding: 5px 10px;
		box-sizing: border-box;
		display: flex;
		align-items: center;
		cursor: pointer;
	}
}
.label {
	font-size: 30px;
	background: rgba(3, 15, 39, 0.6);
	border: 1px solid rgba(76, 107, 209, 0.5);
	width: 320px;
	z-index: 10;
	.val {
		font-weight: bold;
		font-size: 16px;
		color: #ffffff;
		text-shadow: 0px 1px 1px 0px rgba(4, 18, 42, 0.6);
	}
	.name {
		font-size: 12px;
		color: rgba(255, 255, 255, 0.6);
	}
}
</style>
